const md5 = require('blueimp-md5');
const { getCookieStr, getCookie, getHash } = require("./api");
const { isWxApp } = require("./util");


export const request = isWxApp() ? wxrequest : webrequest;


function webrequest(url, data = {}, method = 'POST', userLogin = false) {
  const params = {
    headers: {
      'Content-type': 'application/x-www-form-urlencoded; charset=UTF-8',
    }
  };

  if (userLogin) {
    params.credentials = 'include';
  }

  params.method = method;

  let encryptedParams = encrypt(data, userLogin);
  url += '?_mt=' + encryptedParams._mt;
  delete encryptedParams._mt;

  params.body = serialize(encrypt(data, userLogin));

  return fetch(url, params)
    .then((response) => { return response.json(); })
    .then((res) => {
      const code = res.stat.code;
      if ([-360, -320, -300].indexOf(code) !== -1) {
        return Promise.reject(new Error("no login"));
      }
      return Promise.resolve(res);
    }).catch((e) => {
      if (e.code) {
        return Promise.reject(e);
      }
      return Promise.reject({ name: e.name, message: e.message, logEMsg: { url: `${url}/${data._mt}`, params, res: e.toString() } });
    });
}

/**
 * 封封微信的的request
 */
function wxrequest(url, data = {}, method = 'POST', userLogin = true) {
  let _header = {
    'Content-Type': 'application/json',
  };

  let encryptedParams = encrypt(data, userLogin);
  //post情况下, 以form data模式传递数据
  if (method === 'POST') {
    _header = Object.assign({}, _header, { 'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8' });
    url += '?_mt=' + encryptedParams._mt;
    delete encryptedParams._mt;
    data = Object.assign({}, encryptedParams);
  } else {
    data = encryptedParams;
  }

  return new Promise(function(resolve, reject) {
    wx.request({
      url: url,
      data: data,
      method: method,
      header: _header,
      success: function(res) {
        console.log('request success');
        if (res.statusCode == 200) {
          const code = res.data.stat.code;
          if ([-360, -320, -300].indexOf(code) !== -1) {
            reject(new Error("no login"));
          } else {
            resolve(res.data);
          }
        } else {
          reject(res.errMsg);
        }
      },
      fail: function(err) {
        reject(err);
        console.log('failed');
      }
    });
  });
}

export function checkError(res) {
  const { stat } = res;
  const { code, stateList } = stat;
  if (code != 0) return newError(code, 'bad gateway');
  let err = (Array.isArray(stateList) && stateList.find(v => v.code != 0));
  if (!err) return null;
  return newError(err.code, err.desc || err.msg);
}

export function newError(code, msg) {
  let err = new Error(msg);
  err.code = code;
  return err;
}


function encrypt(data, userLogin = true) {
  const wtkStr = getHash();

  let mergedParams = Object.assign({
      '_sm': 'md5'
    }, data),
    paramStringList = [],
    keys = [];
  Object
    .keys(mergedParams)
    .forEach(key => {
      keys.push(key);
    });
  keys.sort();
  keys.forEach(key => {
    if (typeof mergedParams[key] !== 'undefined') {
      paramStringList.push('' + key + '=' + mergedParams[key]);
    }
  });
  paramStringList.push(wtkStr);

  mergedParams._sig = md5(paramStringList.join(''));
  return mergedParams;
}


// 序列化请求参数
export function serialize(obj, prefix) {
  const str = [];
  for (let p in obj) {
    if (obj.hasOwnProperty(p)) {
      const k = prefix ? `${prefix}[${p}]` : p;
      const v = obj[p];

      str.push(`${encodeURIComponent(k)}=${encodeURIComponent(v)}`);
    }
  }
  return str.join('&');
}
